package cn.virens.mybatis.mapper.example.mapper;

import java.util.List;
import java.util.Map;

import org.apache.ibatis.annotations.DeleteProvider;
import org.apache.ibatis.annotations.Lang;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.SelectProvider;
import org.apache.ibatis.annotations.UpdateProvider;

import cn.virens.mybatis.mapper.example.Example;
import io.mybatis.provider.Caching;

public interface ExampleMapper<T> {

	/**
	 * 根据 Example 删除
	 *
	 * @param  example 条件
	 * @return         大于等于1成功，0失败
	 */
	@Lang(Caching.class)
	@DeleteProvider(type = ExampleProvider.class, method = "deleteByExample")
	int deleteByExample(@Param("example") Example example);

	/**
	 * 根据 Example 条件批量更新实体信息
	 *
	 * @param  entity  实体类
	 * @param  example 条件
	 * @return         大于等于1成功，0失败
	 */
	@Lang(Caching.class)
	@UpdateProvider(type = ExampleProvider.class, method = "updateByExample")
	int updateByExample(@Param("entity") T entity, @Param("example") Example example);

	/**
	 * 根据 Example 条件批量更新实体不为空的字段
	 *
	 * @param  entity  实体类
	 * @param  example 条件
	 * @return         大于等于1成功，0失败
	 */
	@Lang(Caching.class)
	@UpdateProvider(type = ExampleProvider.class, method = "updateByExampleSelective")
	int updateByExampleSelective(@Param("entity") T entity, @Param("example") Example example);

	/**
	 * 根据 Example 条件批量查询
	 *
	 * @param  example 条件
	 * @return         实体列表
	 */
	@Lang(Caching.class)
	@SelectProvider(type = ExampleProvider.class, method = "selectByExample")
	List<T> selectByExample(@Param("example") Example example);

	/**
	 * 根据 Example 条件批量查询
	 *
	 * @param  example 条件
	 * @return         实体列表
	 */
	@Lang(Caching.class)
	@SelectProvider(type = ExampleProvider.class, method = "selectByExample")
	List<Map<String, Object>> selectMapByExample(@Param("example") Example example);

	/**
	 * 根据 Example 条件批量查询
	 *
	 * @param  example 条件
	 * @return         实体列表
	 */
	@Lang(Caching.class)
	@SelectProvider(type = ExampleProvider.class, method = "selectCountByExample")
	long selectCountByExample(@Param("example") Example example);

	/**
	 * 根据 Example 条件单条查询
	 *
	 * @param  example 条件
	 * @return         实体列表
	 */
	default T selectOneByExample(@Param("example") Example example) {
		if (example != null) example.setLimitByClause(1);

		List<T> list = selectByExample(example);
		if (list != null && !list.isEmpty()) {
			return list.get(0);
		} else {
			return null;
		}
	}
}
